/*
 * FaceCat图形通讯框架(非开源)
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

#include "stdafx.h"
#include "FCView.h"
#include "FCPaint.h"
#include "FCNative.h"
#include "FCTran.h"

namespace FaceCat{
    FCAtrEx::FCAtrEx(){
        m_maximumSize.cx = 100000;
        m_maximumSize.cy = 100000;
        m_minimumSize.cx = 0;
        m_minimumSize.cy = 0;
        m_percentLocation = 0;
        m_percentSize = 0;
        m_region.left = 0;
        m_region.top = 0;
        m_region.right = 0;
        m_region.bottom = 0;
        m_useRegion = false;
        m_allowDrag = false;
        m_allowPreviewsEvent = false;
        m_autoEllipsis = false;
        m_autoSize = false;
        m_tabIndex = 0;
        m_tabStop = false;
        m_tag = 0;
        m_cornerRadius = 0;
        m_cursor = FCCursors_Arrow;
        m_displayOffset = true;
        m_isDragging = false;
        m_isWindow = false;
        m_dock = FCDockStyle_None;
        m_canFocus = true;
        m_borderWidth = 1;
    }

    FCAtrEx::~FCAtrEx(){
        m_tag = 0;
        for(int i = 0; i < m_events.size(); i++){
            delete m_events.getValue(i);
        }
        m_events.clear();
        for(int i = 0; i < m_invokes.size(); i++){
            delete m_invokes.getValue(i);
        }
        m_invokes.clear();
        if(m_percentLocation){
            delete m_percentLocation;
            m_percentLocation = 0;
        }
        if(m_percentSize){
            delete m_percentSize;
            m_percentSize = 0;
        }
    }

    void FCView::callEvents(String eventName){
        if(m_atrEx && m_atrEx->m_events.size() > 0){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                int eventSize = (int)events->size();
                for(int i = 0; i < eventSize; i++){
                    FCEventCallBack *func = (FCEventCallBack*)(events->get(i));
                    func->callEvent(eventName, this, invokes->get(i));
                }
            }
        }
    }

    void FCView::callInvokeEvents(String eventName, Object args){
        if(m_atrEx && m_atrEx->m_events.size() > 0){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                int eventSize = (int)events->size();
                for(int i = 0; i < eventSize; i++){
                    FCInvokeEventCallBack *func = (FCInvokeEventCallBack*)(events->get(i));
                    func->callInvokeEvent(eventName, this, args, invokes->get(i));
                }
            }
        }
    }

    void FCView::callKeyEvents(String eventName, char key){
        if(m_atrEx && m_atrEx->m_events.size() > 0){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                int eventSize = (int)events->size();
                for(int i = 0; i < eventSize; i++){
                    FCKeyEventCallBack *func = (FCKeyEventCallBack*)(events->get(i));
                    func->callKeyEvent(eventName, this, key, invokes->get(i));
                }
            }
        }
    }

    void FCView::callTouchEvents(String eventName, FCTouchInfo touchInfo){
        if(m_atrEx && m_atrEx->m_events.size() > 0){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                int eventSize = (int)events->size();
                for(int i = 0; i < eventSize; i++){
                    FCTouchEventCallBack *func = (FCTouchEventCallBack*)(events->get(i));
                    func->callTouchEvent(eventName, this, touchInfo, invokes->get(i));
                }
            }
        }
    }

    bool FCView::callPaintEvents(String eventName, FCPaint *paint, const FCRect& clipRect){
        if(m_atrEx && m_atrEx->m_events.size() > 0){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                int eventSize = (int)events->size();
                for(int i = 0; i < eventSize; i++){
                    FCPaintEventCallBack *func = (FCPaintEventCallBack*)(events->get(i));
                    if(func->callPaintEvent(eventName, this, paint, clipRect, invokes->get(i))){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    bool FCView::callPreviewsKeyEvent(String eventName, String tEventID, char key){
        if(m_atrEx && m_atrEx->m_events.size() > 0){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                int eventSize = (int)events->size();
                for(int i = 0; i < eventSize; i++) {
                    FCPreviewsKeyEventCallBack *func = (FCPreviewsKeyEventCallBack *) (events->get(i));
                    if (func->callPreviewsKeyEvent(eventName, tEventID, this, key,
                                                   invokes->get(i))) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    bool FCView::callPreviewsTouchEvent(String eventName, String tEventID, FCTouchInfo touchInfo){
        if(m_atrEx && m_atrEx->m_events.size() > 0){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                int eventSize = (int)events->size();
                for(int i = 0; i < eventSize; i++){
                    FCPreviewsTouchEventCallBack *func = (FCPreviewsTouchEventCallBack*)(events->get(i));
                    if(func->callPreviewsTouchEvent(eventName, tEventID, this, touchInfo, invokes->get(i))){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    void FCView::callTimerEvents(String eventName, int timerID){
        if(m_atrEx && m_atrEx->m_events.size() > 0){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                int eventSize = (int)events->size();
                for(int i = 0; i < eventSize; i++){
                    FCTimerEventCallBack *func = (FCTimerEventCallBack*)(events->get(i));
                    func->callTimerEvent(eventName, this, timerID, invokes->get(i));
                }
            }
        }
    }
    
    Long FCView::getPaintingBackColor(){
        if (m_backColor != FCColor_None && FCColor_DisabledBack != FCColor_None){
            if (!isPaintEnabled(this)){
                return FCColor_DisabledBack;
            }
        }
        return m_backColor;
    }
    
    String FCView::getPaintingBackImage(){
        return getBackImage();
    }
    
    Long FCView::getPaintingBorderColor(){
        return m_borderColor;
    }
    
    Long FCView::getPaintingTextColor(){
        if (m_textColor != FCColor_Text && FCColor_DisabledText != FCColor_None){
            if (!isPaintEnabled(this)){
                return FCColor_DisabledText;
            }
        }
        return m_textColor;
    }
    
    /////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    FCView::FCView(){
        m_align = FCHorizontalAlign_Left;
        m_backColor = FCColor_Back;
        m_borderColor = FCColor_Border;
        m_enabled = true;
        m_font = new FCFont();
        m_textColor = FCColor_Text;
        m_location.x = 0;
        m_location.y = 0;
        m_native = 0;
        m_oldSize.cx = 0;
        m_oldSize.cy = 0;
        m_opacity = 1;
        m_parent = 0;
        m_size.cx = 0;
        m_size.cy = 0;
        m_topMost = false;
        m_verticalAlign = FCVerticalAlign_Top;
        m_visible = true;
        m_atrEx = 0;
        //m_name = FCTran::stringToString(ret); //TDOO
    }
    
    FCView::~FCView(){
        if(m_font){
            delete m_font;
            m_font = 0;
        }
        if(m_atrEx){
            delete m_atrEx;
            m_atrEx = 0;
        }
        clearViews();
        m_native = 0;
        m_parent = 0;
    }
    
    FCHorizontalAlign FCView::getAlign(){
        return m_align;
    }
    
    void FCView::setAlign(FCHorizontalAlign value){
        m_align = value;
    }
    
    bool FCView::allowDrag(){
        if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_allowDrag;
    }
    
    void FCView::setAllowDrag(bool value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_allowDrag = value;
    }
    
    bool FCView::allowPreviewsEvent(){
        if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_allowPreviewsEvent;
    }
    
    void FCView::setAllowPreviewsEvent(bool value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_allowPreviewsEvent = value;
    }
    
    FCAnchor FCView::getAnchor(){
        if(!m_atrEx){
            FCAnchor anchor;
            return anchor;
        }
        return m_atrEx->m_anchor;
    }
    
    void FCView::setAnchor(const FCAnchor& value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_anchor = value;
    }
    
    bool FCView::autoEllipsis(){
        if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_autoEllipsis;
    }
    
    void FCView::setAutoEllipsis(bool value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_autoEllipsis = value;
    }
    
    bool FCView::autoSize(){
        if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_autoSize;
    }
    
    void FCView::setAutoSize(bool value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_autoSize != value){
            m_atrEx->m_autoSize = value;
            onAutoSizeChanged();
        }
    }
    
    Long FCView::getBackColor(){
        return m_backColor;
    }
    
    void FCView::setBackColor(Long value){
        if(m_backColor != value){
            m_backColor = value;
            onBackColorChanged();
        }
    }
    
    String FCView::getBackImage(){
        if(!m_atrEx){
            return L"";
        }
        return m_atrEx->m_backImage;
    }
    
    void FCView::setBackImage(const String& value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_backImage != value){
            m_atrEx->m_backImage = value;
            onBackImageChanged();
        }
    }
    
    Long FCView::getBorderColor(){
        return m_borderColor;
    }
    
    void FCView::setBorderColor(Long value){
        m_borderColor = value;
    }

    int FCView::getBorderWidth(){
		if (!m_atrEx){
            return 1;
        }
        else{
            return m_atrEx->m_borderWidth;
        }
	}

	void FCView::setBorderWidth(int value){
		if (!m_atrEx){
            m_atrEx = new FCAtrEx();
        }
        m_atrEx->m_borderWidth = value;
	}
    
    int FCView::getBottom(){
        return getTop() + getHeight();
    }
    
    FCRect FCView::getBounds(){
        FCRect rect = {getLeft(), getTop(), getRight(), getBottom()};
        return rect;
    }
    
    void FCView::setBounds(const FCRect& value){
        FCPoint location ={value.left, value.top};
        setLocation(location);
        int cx = value.right - value.left;
        int cy = value.bottom - value.top;
        FCSize size = {cx, cy};
        setSize(size);
    }

    void FCView::setBounds2(const FCRect& value){
        if(m_atrEx){
            setBounds(value);
        }else{
            m_location.x = value.left;
            m_location.y = value.top;
            m_size.cx = value.right - value.left;
            m_size.cy = value.bottom - value.top;
        }
    }

    bool FCView::canFocus(){
        if (!m_atrEx)
        {
            return true;
        }
        return m_atrEx->m_canFocus;
    }

    void FCView::setCanFocus(bool value){
        if (!m_atrEx)
        {
            m_atrEx = new FCAtrEx();
        }
        m_atrEx->m_canFocus = value;
    }
    
    bool FCView::isCapture(){
        if (m_native){
            if (m_native->getHoveredView() == this || m_native->getPushedView() == this){
                return true;
            }
        }
        return false;
    }
    
    int FCView::getCornerRadius(){
        if(!m_atrEx){
            return 0;
        }
        return m_atrEx->m_cornerRadius;
    }
    
    void FCView::setCornerRadius(int value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_cornerRadius = value;
    }
    
    FCCursors FCView::getCursor(){
        if(!m_atrEx){
            return FCCursors_Arrow;
        }
        return m_atrEx->m_cursor;
    }
    
    void FCView::setCursor(FCCursors value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_cursor = value;
    }
    
    bool FCView::displayOffset(){
        if(!m_atrEx){
            return true;
        }
        return m_atrEx->m_displayOffset;
    }
    
    void FCView::setDisplayOffset(bool value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_displayOffset = value;
    }
    
    FCRect FCView::getDisplayRect(){
        if (m_atrEx && m_atrEx->m_useRegion){
            return m_atrEx->m_region;
        }
        else{
            FCRect displayRect ={0, 0, getWidth(), getHeight()};
            return displayRect;
        }
    }
    
    FCDockStyle FCView::getDock(){
        if(!m_atrEx){
            return FCDockStyle_None;
        }
        return m_atrEx->m_dock;
    }
    
    void FCView::setDock(FCDockStyle value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_dock != value){
            m_atrEx->m_dock = value;
            onDockChanged();
        }
    }
    
    bool FCView::isEnabled(){
        return m_enabled;
    }
    
    void FCView::setEnabled(bool value){
        if(m_enabled != value){
            m_enabled = value;
            onEnableChanged();
        }
    }
    
    bool FCView::isFocused(){
        if (m_native){
            if (m_native->getFocusedView() == this){
                return true;
            }
        }
        return false;
    }
    
    void FCView::setFocused(bool value){
        if (m_native){
            if (value){
                m_native->setFocusedView(this);
            }
            else{
                if (m_native->getFocusedView() == this){
                    m_native->setFocusedView(0);
                }
            }
        }
    }
    
    FCFont* FCView::getFont(){
        return m_font;
    }
    
    void FCView::setFont(FCFont *value){
        m_font->copy(value);
        onFontChanged();
    }

    int FCView::getHeight(){
        if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cy != -1){
            FCSize parentSize = m_parent ? m_parent->getSize() : m_native->getSize();
            return (int)(parentSize.cy * m_atrEx->m_percentSize->cy);
        }
        else{
            return m_size.cy;
        }
    }
    
    void FCView::setHeight(int value){
        if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cy != -1){
            return;
        }
        else{
            FCSize size ={m_size.cx, value};
            setSize(size);
        }
    }
    
    bool FCView::isDragging(){
        if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_isDragging;
    }
    
    bool FCView::isWindow(){
        if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_isWindow;
    }
    
    void FCView::setWindow(bool value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_isWindow = value;
    }
    
    int FCView::getLeft(){
        if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->x != -1){
            FCSize parentSize = m_parent ? m_parent->getSize() : m_native->getSize();
            return (int)(parentSize.cx * m_atrEx->m_percentLocation->x);
        }
        else{
            return m_location.x;
        }
    }
    
    void FCView::setLeft(int value){
        if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->x != -1){
            return;
        }
        else{
            FCPoint location = {value, m_location.y};
            setLocation(location);
        }
    }
    
    FCPoint FCView::getLocation(){
        if(m_atrEx && m_atrEx->m_percentLocation){
            FCPoint location ={getLeft(), getTop()};
            return location;
        }
        else{
            return m_location;
        }
    }
    
    void FCView::setLocation(const FCPoint& value){
        if(value.x != m_location.x || value.y != m_location.y){
            if(m_atrEx && m_atrEx->m_percentLocation){
                if(m_atrEx->m_percentLocation->x != -1){
                }
                else{
                    m_location.x = value.x;
                }
                if(m_atrEx->m_percentLocation->y != -1){
                }
                else{
                    m_location.y = value.y;
                }
            }
            else{
                m_location = value;
            }
            onLocationChanged();
        }
    }
    
    FCPadding FCView::getMargin(){
        if(!m_atrEx){
            FCPadding margin(0);
            return margin;
        }
        return m_atrEx->m_margin;
    }
    
    void FCView::setMargin(const FCPadding& value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_margin = value;
        onMarginChanged();
    }
    
    FCSize FCView::getMaximumSize(){
        if(!m_atrEx){
            return {100000, 100000};
        }
        return m_atrEx->m_maximumSize;
    }
    
    void FCView::setMaximumSize(FCSize value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_maximumSize = value;
    }
    
    FCSize FCView::getMinimumSize(){
        if(!m_atrEx){
            return {0};
        }
        return m_atrEx->m_minimumSize;
    }
    
    void FCView::setMinimumSize(FCSize value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_minimumSize = value;
    }
    
    FCPoint FCView::getTouchPoint(){
        if(m_native){
            FCPoint mp = m_native->getTouchPoint();
            return pointToView(mp);
        }
        else{
            FCPoint mp ={0};
            return mp;
        }
    }
    
    String FCView::getName(){
        return m_name;
    }
    
    void FCView::setName(const String& value){
        m_name = value;
    }
    
    FCNative* FCView::getNative(){
        return m_native;
    }
    
    void FCView::setNative(FCNative *value){
        m_native = value;
        int viewsSize = (int)m_views.size();
        for(int i = 0; i < viewsSize; i++){
            m_views.get(i)->setNative(value);
        }
        onLoad();
    }
    
    float FCView::getOpacity(){
        return m_opacity;
    }
    
    void FCView::setOpacity(float value){
        m_opacity = value;
    }
    
    FCPadding FCView::getPadding(){
        if(!m_atrEx){
            FCPadding padding(0);
            return padding;
        }
        return m_atrEx->m_padding;
    }
    
    void FCView::setPadding(const FCPadding& value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_padding = value;
        onPaddingChanged();
    }
    
    FCView* FCView::getParent(){
        return m_parent;
    }
    
    void FCView::setParent(FCView *value){
        if(m_parent != value){
            m_parent = value;
            onParentChanged();
        }
    }
    
    FCRect FCView::getRegion(){
        if(!m_atrEx){
            return {0};
        }
        return m_atrEx->m_region;
    }
    
    void FCView::setRegion(const FCRect& value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_useRegion = true;
        m_atrEx->m_region = value;
        onRegionChanged();
    }

    int FCView::getRight(){
        return getLeft() + getWidth();
    }
    
    FCSize FCView::getSize(){
        if(m_atrEx && m_atrEx->m_percentSize){
            FCSize size ={getWidth(), getHeight()};
            return size;
        }
        else{
            return m_size;
        }
    }
    
    void FCView::setSize(const FCSize& value){
        FCSize newSize = value;
        if(newSize.cx < 0){
            newSize.cx = 0;
        }
        if(newSize.cy < 0){
            newSize.cy = 0;
        }
        if(m_atrEx){
            if (newSize.cx > m_atrEx->m_maximumSize.cx){
                newSize.cx = m_atrEx->m_maximumSize.cx;
            }
            if (newSize.cy > m_atrEx->m_maximumSize.cy){
                newSize.cy = m_atrEx->m_maximumSize.cy;
            }
            if (newSize.cx < m_atrEx->m_minimumSize.cx){
                newSize.cx = m_atrEx->m_minimumSize.cx;
            }
            if (newSize.cy < m_atrEx->m_minimumSize.cy){
                newSize.cy = m_atrEx->m_minimumSize.cy;
            }
        }
        if(newSize.cx != m_size.cx || newSize.cy != m_size.cy){
            if(m_atrEx && m_atrEx->m_percentSize){
                m_oldSize = getSize();
                if(m_atrEx->m_percentSize->cx != -1){
                }
                else{
                    m_size.cx = newSize.cx;
                }
                if(m_atrEx->m_percentSize->cy != -1){
                }
                else{
                    m_size.cy = newSize.cy;
                }
            }
            else{
                m_oldSize = m_size;
                m_size = newSize;
            }
            onSizeChanged();
            update();
        }
    }
    
    int FCView::getTabIndex(){
        if(!m_atrEx){
            return 0;
        }
        return m_atrEx->m_tabIndex;
    }
    
    void FCView::setTabIndex(int value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_tabIndex != value){
            m_atrEx->m_tabIndex = value;
            onTabIndexChanged();
        }
    }
    
    bool FCView::isTabStop(){
        if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_tabStop;
    }
    
    void FCView::setTabStop(bool value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        if(m_atrEx->m_tabStop != value){
            m_atrEx->m_tabStop = value;
            onTabStopChanged();
        }
    }
    
    Object FCView::getTag(){
        if(!m_atrEx){
            return 0;
        }
        return m_atrEx->m_tag;
    }
    
    void FCView::setTag(Object value){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_tag = value;
    }
    
    String FCView::getText(){
        return m_text;
    }
    
    void FCView::setText(const String& value){
        if(m_text != value){
            m_text = value;
            onTextChanged();
        }
    }
    
    Long FCView::getTextColor(){
        return m_textColor;
    }
    
    void FCView::setTextColor(Long value){
        if(m_textColor != value){
            m_textColor = value;
            onTextColorChanged();
        }
    }
    
    int FCView::getTop(){
        if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->y != -1){
            FCSize parentSize = m_parent ? m_parent->getSize() : m_native->getSize();
            return (int)(parentSize.cy * m_atrEx->m_percentLocation->y);
        }
        else{
            return m_location.y;
        }
    }
    
    void FCView::setTop(int top){
        if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->y != -1){
            return;
        }
        else{
            FCPoint location = {m_location.x, top};
            setLocation(location);
        }
    }
    
    bool FCView::isTopMost(){
        return m_topMost;
    }
    
    void FCView::setTopMost(bool value){
        m_topMost = value;
    }
    
    bool FCView::useRegion(){
        if(!m_atrEx){
            return false;
        }
        return m_atrEx->m_useRegion;
    }
    
    FCVerticalAlign FCView::getVerticalAlign(){
        return m_verticalAlign;
    }
    
    void FCView::setVerticalAlign(FCVerticalAlign top){
        m_verticalAlign = top;
    }
    
    bool FCView::isVisible(){
        return m_visible;
    }
    
    void FCView::setVisible(bool value){
        if(m_visible != value){
            m_visible = value;
            onVisibleChanged();
        }
    }
    
    int FCView::getWidth(){
        if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cx != -1){
            FCSize parentSize = m_parent ? m_parent->getSize() : m_native->getSize();
            return (int)(parentSize.cx * m_atrEx->m_percentSize->cx);
        }
        else{
            return m_size.cx;
        }
    }
    
    void FCView::setWidth(int top){
        if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cx != -1){
            return;
        }
        else{
            FCSize size = {top, m_size.cy};
            setSize(size);
        }
    }
    
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    void FCView::addView(FCView *view){
        view->setParent(this);
        view->setNative(m_native);
        m_views.add(view);
        view->onAdd();
    }
    
    void FCView::addEvent(Object func, const String& eventName, Object pInvoke){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        ArrayList<Object> *events = 0;
        ArrayList<Object> *invokes = 0;
        if(m_atrEx->m_events.containsKey(eventName)){
            events = m_atrEx->m_events.get(eventName);
            invokes = m_atrEx->m_invokes.get(eventName);
        }
        else{
            events = new ArrayList<Object>;
            m_atrEx->m_events.put(eventName, events);
            invokes = new ArrayList<Object>;
            m_atrEx->m_invokes.put(eventName, invokes);
        }
        events->add(func);
        invokes->add(pInvoke);
    }
    
    void FCView::beginInvoke(Object args){
        if (m_native){
            FCHost *host = m_native->getHost();
            host->beginInvoke(this, args);
        }
    }
    
    void FCView::bringChildToFront(FCView *childView){
        if(m_views.size() > 0){
            for(int c = 0; c < m_views.size(); c++){
                if(m_views.get(c) == childView){
                    m_views.removeAt(c);
                    break;
                }
            }
            m_views.add(childView);
        }
    }
    
    void FCView::bringToFront(){
        if(m_native){
            m_native->bringToFront(this);
        }
    }
    
    void FCView::clearViews(){
        while((int)m_views.size() > 0){
            FCView *view = m_views.get(0);
            m_views.removeAt(0);
            view->onRemove();
            delete view;
        }
    }
    
    bool FCView::containsView(FCView *view){
        if(m_views.size() > 0){
            for(int c = 0; c < m_views.size(); c++){
                if(m_views.get(c) == view){
                    return true;
                }
            }
        }
        return false;
    }
    
    bool FCView::containsPoint(const FCPoint& mp){
        FCPoint cPoint = pointToView(mp);
        FCSize size = getSize();
        if (cPoint.x >= 0 && cPoint.x <= size.cx && cPoint.y >= 0 && cPoint.y <= size.cy){
            if (m_atrEx && m_atrEx->m_useRegion){
                if (cPoint.x >= m_atrEx->m_region.left && cPoint.x <= m_atrEx->m_region.right
                    && cPoint.y >= m_atrEx->m_region.top && cPoint.y <= m_atrEx->m_region.bottom){
                    return true;
                }
            }
            else{
                return true;
            }
        }
        return false;
    }
    
    void FCView::focus(){
        setFocused(true);
    }
    
    ArrayList<FCView*> FCView::getViews(){
        return m_views;
    }
    
    String FCView::getViewType(){
        return L"View";
    }
    
    FCPoint FCView::getDisplayOffset(){
        FCPoint offset = {0, 0};
        return offset;
    }
    
    static int m_timerID = 10000;
    
    int FCView::getNewTimerID(){
        return m_timerID++;
    }

    String FCView::getAttribute(const String& name){
        String value, type;
        getAttribute(name, &value, &type);
        return value;
    }
    
    void FCView::getAttribute(const String& name, String *value, String *type){
        int len = (int)name.length();
        switch (len){
            case 1:{
                if (name == L"x"){
                    *type = L"float";
                    if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->x != -1){
                        *value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentLocation->x);
                    }
                    else{
                        *value = FCTran::intToStr(getLeft());
                    }
                }else if (name == L"y"){
                    *type = L"float";
                    if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->y != -1){
                        *value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentLocation->y);
                    }
                    else{
                        *value = FCTran::intToStr(getTop());
                    }
                }
                break;
            }
            case 2:{
                if(name == L"id"){
                    *type = L"text";
                    *value = getName();
                }
                break;
            }
            case 3:{
                if (name == L"top"){
                    *type = L"float";
                    if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->y != -1){
                        *value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentLocation->y);
                    }
                    else{
                        *value = FCTran::intToStr(getTop());
                    }
                }
                break;
            }
            case 4:{
                if (name == L"dock"){
                    *type = L"enum:FCDockStyle";
                    *value = FCTran::dockToStr(getDock());
                }
                else if (name == L"font"){
                    *type = L"font";
                    *value = FCTran::fontToStr(getFont());
                }
                else if (name == L"left"){
                    *type = L"float";
                    if(m_atrEx && m_atrEx->m_percentLocation && m_atrEx->m_percentLocation->x != -1){
                        *value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentLocation->x);
                    }
                    else{
                        *value = FCTran::intToStr(getLeft());
                    }
                }
                else if (name == L"name"){
                    *type = L"text";
                    *value = getName();
                }
                else if (name == L"size"){
                    *type = L"size";
                    if (m_atrEx && m_atrEx->m_percentSize){
                        String pWidth, pHeight, pType;
                        getAttribute(L"width", &pWidth, &pType);
                        getAttribute(L"height", &pHeight, &pType);
                        *value = pWidth + L"," + pHeight;
                    }
                    else{
                        *value = FCTran::sizeToStr(getSize());
                    }
                }
                else if (name == L"text"){
                    *type = L"text";
                    *value = getText();
                }
                break;
            }
            case 5:{
                if (name == L"align"){
                    *type = L"enum:FCHorizontalAlign";
                    *value = FCTran::horizontalAlignToStr(getAlign());
                }
                else if(name == L"value"){
                    *type = L"text";
                    *value = getText();
                }
                else if (name == L"width"){
                    *type = L"float";
                    if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cx != -1){
                        *value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentSize->cx);
                    }
                    else{
                        *value = FCTran::intToStr(getWidth());
                    }
                }
                break;
            }
            case 6:{
                if (name == L"anchor"){
                    *type = L"anchor";
                    *value = FCTran::anchorToStr(getAnchor());
                }
                else if (name == L"bounds"){
                    *type = L"rect";
                    *value = FCTran::rectToStr(getBounds());
                }
                else if (name == L"cursor"){
                    *type = L"enum:FCCursors";
                    *value = FCTran::cursorToStr(getCursor());
                }
                else if (name == L"height"){
                    *type = L"float";
                    if(m_atrEx && m_atrEx->m_percentSize && m_atrEx->m_percentSize->cy != -1){
                        *value = String(L"%") + FCTran::floatToStr(100 * m_atrEx->m_percentSize->cy);
                    }
                    else{
                        *value = FCTran::intToStr(getHeight());
                    }
                }
                else if (name == L"margin"){
                    *type = L"padding";
                    *value = FCTran::paddingToStr(getMargin());
                }
                else if (name == L"region"){
                    *type = L"rect";
                    *value = FCTran::rectToStr(getRegion());
                }
                break;
            }
            case 7:{
                if (name == L"enabled"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(isEnabled());
                }
                else if (name == L"focused"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(isFocused());
                }
                else if (name == L"opacity"){
                    *type = L"float";
                    *value = FCTran::floatToStr(getOpacity());
                }
                else if (name == L"padding"){
                    *type = L"padding";
                    *value = FCTran::paddingToStr(getPadding());
                }
                else if (name == L"tabstop"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(isTabStop());
                }
                else if (name == L"topmost"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(isTopMost());
                }
                else if (name == L"visible"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(isVisible());
                }
                break;
            }
            case 8:{
                if (name == L"autosize"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(autoSize());
                }
                else if (name == L"iswindow"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(isWindow());
                }
                else if (name == L"location"){
                    *type = L"point";
                    if (m_atrEx && m_atrEx->m_percentLocation){
                        String pLeft, pTop, pType;
                        getAttribute(L"left", &pLeft, &pType);
                        getAttribute(L"top", &pTop, &pType);
                        *value = pLeft + L"," + pTop;
                    }
                    else{
                        *value = FCTran::pointToStr(getLocation());
                    }
                }
                else if (name == L"tabindex"){
                    *type = L"int";
                    *value = FCTran::intToStr(getTabIndex());
                }
                else if (name == L"canfocus"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(canFocus());
                }
                break;
            }
            case 9:{
                if (name == L"allowdrag"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(allowDrag());
                }
                else if (name == L"backcolor"){
                    *type = L"color";
                    *value = FCTran::colorToStr(getBackColor());
                }
                else if (name == L"backimage"){
                    *type = L"text";
                    *value = getBackImage();
                }
                else if (name == L"textcolor"){
                    *type = L"color";
                    *value = FCTran::colorToStr(getTextColor());
                }
                break;
            }
            default:{
                if (name == L"allowpreviewsevent"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(allowPreviewsEvent());
                }
                else if (name == L"autoellipsis"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(autoEllipsis());
                }
                else if (name == L"bordercolor"){
                    *type = L"color";
                    *value = FCTran::colorToStr(getBorderColor());
                }
                else if(name == L"cornerradius"){
                    *type = L"int";
                    *value = FCTran::intToStr(getCornerRadius());
                }
                else if (name == L"displayoffset"){
                    *type = L"bool";
                    *value = FCTran::boolToStr(displayOffset());
                }
                else if (name == L"maximumsize"){
                    *type = L"size";
                    *value = FCTran::sizeToStr(getMaximumSize());
                }
                else if (name == L"minimumsize"){
                    *type = L"size";
                    *value = FCTran::sizeToStr(getMinimumSize());
                }
                else if (name == L"vertical-align"){
                    *type = L"enum:FCVerticalAlign";
                    *value = FCTran::verticalAlignToStr(getVerticalAlign());
                }else if (name == L"borderwidth")
                {
                    *type = L"int";
					*value = FCTran::intToStr(getBorderWidth());
                }
                break;
            }
        }
    }
    
    ArrayList<String> FCView::getAttributeNames(){
        ArrayList<String> attributeNames;
        attributeNames.add(L"Align");
        attributeNames.add(L"AllowDrag");
        attributeNames.add(L"AllowPreviewsEvent");
        attributeNames.add(L"Anchor");
        attributeNames.add(L"AutoEllipsis");
        attributeNames.add(L"AutoSize");
        attributeNames.add(L"BackColor");
        attributeNames.add(L"BackImage");
        attributeNames.add(L"BorderColor");
        attributeNames.add(L"BorderWidth");
        attributeNames.add(L"Bounds");
        attributeNames.add(L"CanFocus");
        attributeNames.add(L"CornerRadius");
        attributeNames.add(L"Cursor");
        attributeNames.add(L"DisplayOffset");
        attributeNames.add(L"Dock");
        attributeNames.add(L"Enabled");
        attributeNames.add(L"Focused");
        attributeNames.add(L"Font");
        attributeNames.add(L"Height");
        attributeNames.add(L"IsWindow");
        attributeNames.add(L"Left");
        attributeNames.add(L"Location");
        attributeNames.add(L"Margin");
        attributeNames.add(L"MaximumSize");
        attributeNames.add(L"MinimumSize");
        attributeNames.add(L"Name");
        attributeNames.add(L"Opacity");
        attributeNames.add(L"Padding");
        attributeNames.add(L"Region");
        attributeNames.add(L"Size");
        attributeNames.add(L"TabIndex");
        attributeNames.add(L"TabStop");
        attributeNames.add(L"Text");
        attributeNames.add(L"TextColor");
        attributeNames.add(L"Top");
        attributeNames.add(L"TopMost");
        attributeNames.add(L"Value");
        attributeNames.add(L"Vertical-Align");
        attributeNames.add(L"Visible");
        attributeNames.add(L"Width");
        attributeNames.add(L"X");
        attributeNames.add(L"Y");
        return attributeNames;
    }
    
    ArrayList<String> FCView::getEventNames(){
        ArrayList<String> eventNames;
        eventNames.add(L"Add");
        eventNames.add(L"BackColorChanged");
        eventNames.add(L"BackImageChanged");
        eventNames.add(L"Char");
        eventNames.add(L"Click");
        eventNames.add(L"Copy");
        eventNames.add(L"Cut");
        eventNames.add(L"DockChanged");
        eventNames.add(L"DoubleClick");
        eventNames.add(L"DragBegin");
        eventNames.add(L"DragEnd");
        eventNames.add(L"Dragging");
        eventNames.add(L"EnableChanged");
        eventNames.add(L"FontChanged");
        eventNames.add(L"GotFocus");
        eventNames.add(L"Invoke");
        eventNames.add(L"KeyDown");
        eventNames.add(L"KeyUp");
        eventNames.add(L"Load");
        eventNames.add(L"LostFocus");
        eventNames.add(L"MarginChanged");
        eventNames.add(L"TouchDown");
        eventNames.add(L"TouchEnter");
        eventNames.add(L"TouchLeave");
        eventNames.add(L"TouchMove");
        eventNames.add(L"TouchUp");
        eventNames.add(L"TouchWheel");
        eventNames.add(L"PaddingChanged");
        eventNames.add(L"ParentChanged");
        eventNames.add(L"Paint");
        eventNames.add(L"PaintBorder");
        eventNames.add(L"Paste");
        eventNames.add(L"RegionChanged");
        eventNames.add(L"Remove");
        eventNames.add(L"SizeChanged");
        eventNames.add(L"TabIndexChanged");
        eventNames.add(L"TabStop");
        eventNames.add(L"TabStopChanged");
        eventNames.add(L"TextChanged");
        eventNames.add(L"TextColorChanged");
        eventNames.add(L"Timer");
        eventNames.add(L"VisibleChanged");
        return eventNames;
    }
    
    bool FCView::hasChildren(){
        return m_views.size() > 0;
    }
    
    void FCView::hide(){
        setVisible(false);
    }
    
    void FCView::insertView(int index, FCView *view){
        view->setParent(this);
        view->setNative(m_native);
        m_views.insert(index, view);
        view->onAdd();
    }
    
    void FCView::invalidate(){
        if(m_native){
            if(isPaintVisible(this)){
                m_native->invalidate(this);
            }
        }
    }
    
    void FCView::invoke(Object args){
        if (m_native){
            FCHost *host = m_native->getHost();
            host->invoke(this, args);
        }
    }
    
    bool FCView::isPaintEnabled(FCView *view){
        if (view->isEnabled()){
            FCView *parent = view->getParent();
            if (parent){
                return isPaintEnabled(parent);
            }
            else{
                return true;
            }
        }
        else{
            return false;
        }
    }
    
    bool FCView::isPaintVisible(FCView *view){
        if (view->isVisible()){
            FCView *parent = view->getParent();
            if (parent){
                return isPaintVisible(parent);
            }
            else{
                return true;
            }
        }
        else{
            return false;
        }
    }
    
    void FCView::onAdd(){
        callEvents(L"onadd");
    }
    
    void FCView::onAutoSizeChanged(){
        callEvents(L"onautosizechanged");
    }
    
    void FCView::onBackColorChanged(){
        callEvents(L"onbackcolorchanged");
    }
    
    void FCView::onBackImageChanged(){
        callEvents(L"onbackimagechanged");
    }
    
    void FCView::onChar(wchar_t ch){
    }
    
    void FCView::onClick(FCTouchInfo touchInfo){
        callTouchEvents(L"onclick", touchInfo);
    }
    
    void FCView::onCopy(){
        callEvents(L"oncopy");
    }
    
    void FCView::onCut(){
        callEvents(L"oncut");
    }
    
    void FCView::onDockChanged(){
        callEvents(L"ondockchanged");
    }
    
    void FCView::onDoubleClick(FCTouchInfo touchInfo){
        callTouchEvents(L"ondoubleclick", touchInfo);
    }
    
    bool FCView::onDragBegin(){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_isDragging = true;
        callEvents(L"ondragbegin");
        return true;
    }
    
    void FCView::onDragEnd(){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_isDragging = false;
        callEvents(L"ondragend");
    }
    
    void FCView::onDragging(){
        if(!m_atrEx){
            m_atrEx = new FCAtrEx;
        }
        m_atrEx->m_isDragging = true;
        callEvents(L"ondragging");
    }

    void FCView::onDragInFiles(ArrayList<String> *files){
        
    }
    
    void FCView::onDragReady(FCPoint *startOffset){
        startOffset->x = 5;
        startOffset->y = 5;
    }
    
    void FCView::onEnableChanged(){
        callEvents(L"onenablechanged");
    }
    
    void FCView::onFontChanged(){
        callEvents(L"onfontchanged");
    }
    
    void FCView::onGotFocus(){
        callEvents(L"ongotfocus");
    }
    
    void FCView::onInvoke(Object args){
        callInvokeEvents(L"oninvoke", args);
    }
    
    void FCView::onLoad(){
        callEvents(L"onload");
    }
    
    void FCView::onLocationChanged(){
        callEvents(L"onlocationchanged");
    }
    
    void FCView::onLostFocus(){
        callEvents(L"onlostfocus");
    }
    
    void FCView::onKeyDown(char key){
        callKeyEvents(L"onkeydown", key);
        FCHost *host = getNative()->getHost();
        if (host->isKeyPress(0x11)) {
            //复制
            if (key == 67 || key == 99) {
                onCopy();
            }
                //粘贴
            else if (key == 86 || key == 118) {
                onPaste();
            }
                //剪切
            else if (key == 88 || key == 120) {
                onCut();
            }
        }
    }
    
    void FCView::onKeyUp(char key){
        callKeyEvents(L"onkeyup", key);
    }
    
    void FCView::onMarginChanged(){
        callEvents(L"onmarginchanged");
    }
    
    void FCView::onTouchDown(FCTouchInfo touchInfo){
        callTouchEvents(L"ontouchdown", touchInfo);
    }
    
    void FCView::onTouchEnter(FCTouchInfo touchInfo){
        callTouchEvents(L"ontouchenter", touchInfo);
        if (autoEllipsis()){
            if ((int)m_text.length() > 0){
                m_native->getHost()->showToolTip(m_text, m_native->getTouchPoint());
            }
        }
    }
    
    void FCView::onTouchLeave(FCTouchInfo touchInfo){
        callTouchEvents(L"ontouchleave", touchInfo);
    }
    
    void FCView::onTouchMove(FCTouchInfo touchInfo){
        callTouchEvents(L"ontouchmove", touchInfo);
    }
    
    void FCView::onTouchUp(FCTouchInfo touchInfo){
        callTouchEvents(L"ontouchup", touchInfo);
    }
    
    void FCView::onTouchWheel(FCTouchInfo touchInfo){
        callTouchEvents(L"ontouchwheel", touchInfo);
    }
    
    void FCView::onPaddingChanged(){
        callEvents(L"onpaddingchanged");
    }
    
    void FCView::onPaint(FCPaint *paint, const FCRect& clipRect){
        onPaintBackground(paint, clipRect);
        onPaintForeground(paint, clipRect);
        callPaintEvents(L"onpaint", paint, clipRect);
    }
    
    void FCView::onPaintBackground(FCPaint *paint, const FCRect& clipRect){
        FCRect rect ={0, 0, getWidth(), getHeight()};
        paint->fillRoundRect(getPaintingBackColor(), rect, getCornerRadius());
        String bkImage = getPaintingBackImage();
        if ((int)bkImage.length() > 0){
            paint->drawImage(bkImage, rect);
        }
    }
    
    void FCView::onPaintBorder(FCPaint *paint, const FCRect& clipRect){
        FCRect borderRect = {0, 0, getWidth(), getHeight()};
        paint->drawRoundRect(getPaintingBorderColor(), getBorderWidth(), 0, borderRect, getCornerRadius());
        callPaintEvents(L"onpaintborder", paint, clipRect);
    }
    
    void FCView::onPaintForeground(FCPaint *paint, const FCRect& clipRect){
    }
    
    void FCView::onParentChanged(){
        callEvents(L"onparentchanged");
    }
    
    void FCView::onPaste(){
        callEvents(L"onpaste");
    }
    
    bool FCView::onPrePaint(FCPaint *paint, const FCRect& clipRect){
        return callPaintEvents(L"onprepaint", paint, clipRect);
    }
    
    bool FCView::onPreviewsKeyEvent(String eventName, char key){
        return callPreviewsKeyEvent(L"onpreviewskeyevent", eventName, key);
    }
    
    bool FCView::onPreviewsTouchEvent(String eventName, FCTouchInfo touchInfo){
        return callPreviewsTouchEvent(L"onpreviewstouchevent", eventName, touchInfo);
    }
    
    void FCView::onRegionChanged(){
        callEvents(L"onregionchanged");
    }
    
    void FCView::onRemove(){
        callEvents(L"onremove");
    }

    void FCView::onScaling(double scaleFactorX, double scaleFactorY) {
        m_location.x = (int)(m_location.x * scaleFactorX);
        m_location.y = (int)(m_location.y * scaleFactorY);
        m_size.cx = (int)(m_size.cx * scaleFactorX);
        m_size.cy = (int)(m_size.cy * scaleFactorY);
        m_font->m_fontSize = (float)(m_font->m_fontSize * (scaleFactorX + scaleFactorY) / 2);
        if(m_atrEx){
            m_atrEx->m_maximumSize.cx = (int)(m_atrEx->m_maximumSize.cx * scaleFactorX);
            m_atrEx->m_maximumSize.cy = (int)(m_atrEx->m_maximumSize.cy * scaleFactorY);
            m_atrEx->m_minimumSize.cx = (int)(m_atrEx->m_minimumSize.cx * scaleFactorX);
            m_atrEx->m_minimumSize.cy = (int)(m_atrEx->m_minimumSize.cy * scaleFactorY);
        }
        int viewSize = m_views.size();
        for (int i = 0; i < viewSize; i++) {
            m_views.get(i)->onScaling(scaleFactorX, scaleFactorY);
        }
    }
    
    void FCView::onSizeChanged(){
        callEvents(L"onsizechanged");
        update();
    }
    
    void FCView::onTabIndexChanged(){
        callEvents(L"ontabindexchanged");
    }
    
    void FCView::onTabStop(){
        callEvents(L"ontabstop");
    }
    
    void FCView::onTabStopChanged(){
        callEvents(L"ontabstopchanged");
    }
    
    void FCView::onTextChanged(){
        callEvents(L"ontextchanged");
    }
    
    void FCView::onTextColorChanged(){
        callEvents(L"ontextcolorchanged");
    }
    
    void FCView::onTimer(int timerID){
        callTimerEvents(L"ontimer", timerID);
    }
    
    void FCView::onVisibleChanged(){
        callEvents(L"onvisiblechanged");
    }
    
    FCPoint FCView::pointToView(const FCPoint& mp){
        if (m_native){
            int clientX = m_native->clientX(this);
            int clientY = m_native->clientY(this);
            FCPoint point ={mp.x - clientX, mp.y - clientY};
            return point;
        }
        else{
            return mp;
        }
    }
    
    FCPoint FCView::pointToNative(const FCPoint& mp){
        if (m_native){
            int clientX = m_native->clientX(this);
            int clientY = m_native->clientY(this);
            FCPoint point ={mp.x + clientX, mp.y + clientY};
            return point;
        }
        else{
            return mp;
        }
    }
    
    void FCView::removeView(FCView *view){
        if(m_native){
            m_native->clearViewState(view);
        }
        for(int c = 0; c < m_views.size(); c++){
            FCView *baseView = m_views.get(c);
            if(baseView == view){
                baseView->onRemove();
                m_views.removeAt(c);
                view->setParent(0);
                return;
            }
        }
    }
    
    void FCView::removeEvent(Object func, const String& eventName){
        if(m_atrEx){
            if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                int eventSize = (int)events->size();
                int removeIndex = -1;
                for(int i = 0; i < eventSize; i++){
                    if(events->get(i) == func){
                        removeIndex = i;
                        break;
                    }
                }
                if(removeIndex >= 0){
                    ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
                    for(int i = 0; i < eventSize; i++) {
                        if (i == removeIndex) {
                            events->removeAt(i);
                            break;
                        }
                    }
                    for(int i = 0; i < eventSize; i++){
                        if(i == removeIndex){
                            invokes->removeAt(i);
                            break;
                        }
                    }
                }
            }
        }
    }
    
    void FCView::sendChildToBack(FCView *childView){
        if(m_views.size() > 0){
            for(int c = 0; c < m_views.size(); c++){
                if(m_views.get(c) ==  childView){
                    m_views.removeAt(c);
                    break;
                }
            }
            m_views.insert(0, childView);
        }
    }
    
    void FCView::setAttribute(const String& name, const String& value){
        int len = (int)name.length();
        switch (len){
            case 1:{
                if (name == L"x"){
                    if(value.find(L"%") != -1){
                        float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
                        if(!m_atrEx){
                            m_atrEx = new FCAtrEx;
                        }
                        if(!m_atrEx->m_percentLocation){
                            m_atrEx->m_percentLocation = new FCPointF();
                            m_atrEx->m_percentLocation->y = -1;
                        }
                        m_atrEx->m_percentLocation->x = percentValue;
                    }
                    else{
                        if(m_atrEx && m_atrEx->m_percentLocation){
                            m_atrEx->m_percentLocation->x = -1;
                        }
                        setLeft(FCTran::strToInt(value));
                    }
                }else if (name == L"y"){
                    if(value.find(L"%") != -1){
                        if(!m_atrEx){
                            m_atrEx = new FCAtrEx;
                        }
                        float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
                        if(!m_atrEx->m_percentLocation){
                            m_atrEx->m_percentLocation = new FCPointF();
                            m_atrEx->m_percentLocation->x = -1;
                        }
                        m_atrEx->m_percentLocation->y = percentValue;
                    }
                    else{
                        if(m_atrEx->m_percentLocation){
                            m_atrEx->m_percentLocation->y = -1;
                        }
                        setTop(FCTran::strToInt(value));
                    }
                }
                break;
            }
            case 2:{
                if(name == L"id"){
                    setName(value);
                }
            }
            case 3:{
                if (name == L"top"){
                    if(value.find(L"%") != -1){
                        if(!m_atrEx){
                            m_atrEx = new FCAtrEx;
                        }
                        float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
                        if(!m_atrEx->m_percentLocation){
                            m_atrEx->m_percentLocation = new FCPointF();
                            m_atrEx->m_percentLocation->x = -1;
                        }
                        m_atrEx->m_percentLocation->y = percentValue;
                    }
                    else{
                        if(m_atrEx && m_atrEx->m_percentLocation){
                            m_atrEx->m_percentLocation->y = -1;
                        }
                        setTop(FCTran::strToInt(value));
                    }
                }
                break;
            }
            case 4:{
                if (name == L"dock"){
                    setDock(FCTran::strToDock(value));
                }
                else if (name == L"font"){
                    FCFont nFont = FCTran::strToFont(value);
                    setFont(&nFont);
                }
                else if (name == L"left"){
                    if(value.find(L"%") != -1){
                        if(!m_atrEx){
                            m_atrEx = new FCAtrEx;
                        }
                        float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
                        if(!m_atrEx->m_percentLocation){
                            m_atrEx->m_percentLocation = new FCPointF();
                            m_atrEx->m_percentLocation->y = -1;
                        }
                        m_atrEx->m_percentLocation->x = percentValue;
                    }
                    else{
                        if(m_atrEx->m_percentLocation){
                            m_atrEx->m_percentLocation->x = -1;
                        }
                        setLeft(FCTran::strToInt(value));
                    }
                }
                else if (name == L"name"){
                    setName(value);
                }
                else if (name == L"size"){
                    if ((int)value.find(L"%") == -1)
                    {
                        setSize(FCTran::strToSize(value));
                    }
                    else
                    {
                        ArrayList<String> strs = FCTran::split(value, L",");
                        setAttribute(L"width", strs.get(0));
                        setAttribute(L"height", strs.get(1));
                    }
                }
                else if (name == L"text"){
                    setText(value);
                }
                break;
            }
            case 5:{
                if (name == L"align"){
                    setAlign(FCTran::strToHorizontalAlign(value));
                }
                else if(name == L"value"){
                    setText(value);
                }
                else if (name == L"width"){
                    if(value.find(L"%") != -1){
                        if(!m_atrEx){
                            m_atrEx = new FCAtrEx;
                        }
                        float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
                        if(!m_atrEx->m_percentSize){
                            m_atrEx->m_percentSize = new FCSizeF();
                            m_atrEx->m_percentSize->cy = -1;
                        }
                        m_atrEx->m_percentSize->cx = percentValue;
                    }
                    else{
                        if(m_atrEx && m_atrEx->m_percentSize){
                            m_atrEx->m_percentSize->cx = -1;
                        }
                        setWidth(FCTran::strToInt(value));
                    }
                }
                break;
            }
            case 6:{
                if (name == L"anchor"){
                    setAnchor(FCTran::strToAnchor(value));
                }
                else if (name == L"bounds"){
                    setBounds(FCTran::strToRect(value));
                }
                else if (name == L"cursor"){
                    setCursor(FCTran::strToCursor(value));
                }
                else if (name == L"height"){
                    if(value.find(L"%") != -1){
                        if(!m_atrEx){
                            m_atrEx = new FCAtrEx;
                        }
                        float percentValue = FCTran::strToFloat(FCTran::replace(value, L"%", L"")) / 100;
                        if(!m_atrEx->m_percentSize){
                            m_atrEx->m_percentSize = new FCSizeF();
                            m_atrEx->m_percentSize->cx = -1;
                        }
                        m_atrEx->m_percentSize->cy = percentValue;
                    }
                    else{
                        if(m_atrEx && m_atrEx->m_percentSize){
                            m_atrEx->m_percentSize->cy = -1;
                        }
                        setHeight(FCTran::strToInt(value));
                    }
                }
                else if (name == L"margin"){
                    setMargin(FCTran::strToPadding(value));
                }
                else if (name == L"region"){
                    setRegion(FCTran::strToRect(value));
                }
                break;
            }
            case 7:{
                if (name == L"enabled"){
                    setEnabled(FCTran::strToBool(value));
                }
                else if (name == L"focused"){
                    setFocused(FCTran::strToBool(value));
                }
                else if (name == L"opacity"){
                    setOpacity(FCTran::strToFloat(value));
                }
                else if (name == L"padding"){
                    setPadding(FCTran::strToPadding(value));
                }
                else if (name == L"tabstop"){
                    setTabStop(FCTran::strToBool(value));
                }
                else if (name == L"topmost"){
                    setTopMost(FCTran::strToBool(value));
                }
                else if (name == L"visible"){
                    setVisible(FCTran::strToBool(value));
                }
                break;
            }
            case 8:{
                if (name == L"autosize"){
                    setAutoSize(FCTran::strToBool(value));
                }
                else if (name == L"iswindow"){
                    setWindow(FCTran::strToBool(value));
                }
                else if (name == L"location"){
                    if ((int)value.find(L"%") == -1)
                    {
                        setLocation(FCTran::strToPoint(value));
                    }
                    else
                    {
                        ArrayList<String> strs = FCTran::split(value, L",");
                        setAttribute(L"left", strs.get(0));
                        setAttribute(L"top", strs.get(1));
                    }
                }
                else if (name == L"tabindex"){
                    setTabIndex(FCTran::strToInt(value));
                }
                else if (name == L"canfocus"){
                    setCanFocus(FCTran::strToBool(value));
                }
                break;
            }
            case 9:{
                if (name == L"allowdrag"){
                    setAllowDrag(FCTran::strToBool(value));
                }
                else if (name == L"backcolor"){
                    setBackColor(FCTran::strToColor(value));
                }
                else if (name == L"backimage"){
                    setBackImage(value);
                }
                else if (name == L"textcolor"){
                    setTextColor(FCTran::strToColor(value));
                }
                break;
            }
            default:{
                if (name == L"allowpreviewsevent"){
                    setAllowPreviewsEvent(FCTran::strToBool(value));
                }
                else if (name == L"autoellipsis"){
                    setAutoEllipsis(FCTran::strToBool(value));
                }
                else if (name == L"bordercolor"){
                    setBorderColor(FCTran::strToColor(value));
                }
                else if(name == L"cornerradius"){
                    setCornerRadius(FCTran::strToInt(value));
                }
                else if (name == L"displayoffset"){
                    setDisplayOffset(FCTran::strToBool(value));
                }
                else if (name == L"maximumsize"){
                    setMaximumSize(FCTran::strToSize(value));
                }
                else if (name == L"minimumsize"){
                    setMinimumSize(FCTran::strToSize(value));
                }
                else if (name == L"vertical-align"){
                    setVerticalAlign(FCTran::strToVerticalAlign(value));
                }else if (name == L"borderwidth"){
					setBorderWidth(FCTran::strToInt(value));
                }
                break;
            }
        }
    }
    
    void FCView::sendToBack(){
        if(m_native){
            m_native->sendToBack(this);
        }
    }
    
    void FCView::show(){
        setVisible(true);
    }

    bool FCView::showOutOfMirror(){
        return true;
    }
    
    void FCView::startTimer(int timerID, int interval){
        if(m_native){
            m_native->startTimer(this, timerID, interval);
        }
    }
    
    void FCView::stopTimer(int timerID){
        if(m_native){
            m_native->stopTimer(timerID);
        }
    }
    
    void FCView::update(){
        if(m_native && !m_native->m_lockUpdate){
            m_native->setAlign(&m_views);
            if (m_oldSize.cx > 0 && m_oldSize.cy > 0){
                m_native->setAnchor(&m_views, m_oldSize);
            }
            m_native->setDock(&m_views);
            m_oldSize = getSize();
            int viewsSize = (int)m_views.size();
            for (int i = 0; i < viewsSize; i++){
                m_views.get(i)->update();
            }
        }
    }
}
